This notebook generates a set of interactive choropleth maps, showing various metrics of internet quality for different areas in the Province of Alberta. These maps attempt to reconcile all boundaries given in the competition data. Some boundaries were cut into, or overlapped, but parts of the dataset eventually had to be discarded.
import geopandas as gpd
import pandas as pd
from pathlib import Path
import shapely
from folium import Choropleth, Marker
import folium
from helper_functions import show_overlaps, boundary_cut, plot_bounds
file_path = Path("data/Municipal_Boundaries_SHP_Geographic/")
rural_gdf = gpd.read_file(file_path/"RURAL.shp") #1
reserve_gdf = gpd.read_file(file_path/"INDIAN.shp") # 2
city_gdf = gpd.read_file(file_path/"CITY.shp") # 3
town_gdf = gpd.read_file(file_path/"TOWN.shp") # 4
urbserv_gdf = gpd.read_file(file_path/"urbserv.shp") # 5
# hamlet_df = gpd.read_file(file_path/"HAMLETPT.shp") # points, no boundaries
village_gdf = gpd.read_file(file_path/"VILLAGE.shp") # 6
svillage_gdf = gpd.read_file(file_path/"SVILLAGE.shp") # 7
ookla_gdf = gpd.read_file("data/ookla/AB_ookla_data_2020.shp")
ookla_gdf.head(3)
| quadkey | avg_d_kbps | avg_u_kbps | avg_lat_ms | tests | devices | quarter | conn_type | geometry | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0212113033010133 | 807 | 273 | 84 | 1 | 1 | Q1 | fixed | POLYGON ((-114.13147 53.53051, -114.12598 53.5... |
| 1 | 0212113123020220 | 82062 | 11294 | 19 | 34 | 4 | Q1 | fixed | POLYGON ((-113.55469 53.46843, -113.54919 53.4... |
| 2 | 0212131212333013 | 9741 | 1382 | 24 | 7 | 2 | Q1 | fixed | POLYGON ((-114.28528 51.20344, -114.27979 51.2... |
Changing ookla polygons to centroids, for spatial join accuracy.
ookla_gdf["long"] = ookla_gdf.geometry.apply(lambda x:x.centroid.x)
ookla_gdf["lat"] = ookla_gdf.geometry.apply(lambda x:x.centroid.y)
ookla_temp = pd.DataFrame(ookla_gdf.drop("geometry", axis=1))
ookla_gdf = gpd.GeoDataFrame(ookla_temp, geometry=gpd.points_from_xy(
ookla_temp.long, ookla_temp.lat))
ookla_gdf = ookla_gdf.drop(["long", "lat"], axis=1)
ookla_gdf.crs = {"init":"EPSG:4326"}
/home/peter/anaconda3/envs/basic-data/lib/python3.8/site-packages/pyproj/crs/crs.py:53: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6
return _prepare_from_string(" ".join(pjargs))
Cutting smaller boundaries out of the rural boundaries
rural_cuts = [reserve_gdf, city_gdf, town_gdf, urbserv_gdf, village_gdf, svillage_gdf]
rural_gdf = boundary_cut(rural_cuts, rural_gdf)
Cutting smaller boundaries out of reserve boundaries
reserve_cuts = rural_cuts.copy()
reserve_cuts.remove(reserve_gdf)
reserve_gdf = boundary_cut(reserve_cuts, reserve_gdf)
Changing dataframe formats to be used in the folium map:
rural_data = gpd.sjoin(ookla_gdf, rural_gdf.to_crs("+init=epsg:4326 +type=crs"))
/home/peter/anaconda3/envs/basic-data/lib/python3.8/site-packages/pyproj/crs/crs.py:280: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6 projstring = _prepare_from_string(projparams)
rural_dict = rural_data.groupby("GEONAME")["avg_d_kbps"].mean()
rural_final = rural_gdf[["GEONAME", "geometry"]].set_index("GEONAME")
m_test = folium.Map(location=[55,-115], tiles='cartodbpositron', zoom_start=5, width="60%", height="100%")
Choropleth(geo_data=rural_final.__geo_interface__,
data=rural_dict,
key_on="feature.id",
fill_color='YlGnBu',
line_weight=0.5,
legend_name='Internet Test Numbers'
).add_to(m_test)
m_test